package com.reger.saio.core;

import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.reger.saio.CompletedCallBack;
import com.reger.saio.FailedCallBack;

public class ServerSession<T> {
	private static final Logger log = LogManager.getLogger(ServerSession.class);
	private final AsynchronousSocketChannel socketChannel;
	private final T attachment;

	public ServerSession(AsynchronousSocketChannel socketChannel, T attachment) {
		super();
		this.socketChannel = socketChannel;
		this.attachment = attachment;
	}

	public AsynchronousSocketChannel getSocketChannel() {
		return socketChannel;
	}

	private SocketAddress getRemoteAddress() {
		try {
			return socketChannel.getRemoteAddress();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public ServerSession<T> receive(final ByteBuffer buffer, CompletedCallBack<Integer, T> completed,
			FailedCallBack<T> failed) {
		socketChannel.read(buffer, attachment, new CompletionHandler<Integer, T>() {

			@Override
			public void completed(Integer result, T attachment) {
				buffer.flip();
				if (completed != null) {
					completed.completed(result, attachment);
				} else {
					log.info("服务端从{}接受数据完毕", ServerSession.this.getRemoteAddress());
				}
				buffer.clear();
				socketChannel.read(buffer, attachment, this);
			}

			@Override
			public void failed(Throwable exc, T attachment) {
				if (failed != null) {
					failed.failed(exc, attachment);
				} else {
					log.info("服务端从{}接受数据失败", ServerSession.this.getRemoteAddress());
				}
			}

		});
		return this;
	}

	public ServerSession<T> send(final ByteBuffer buffer, CompletedCallBack<Integer, T> completed,
			FailedCallBack<T> failed) {
		socketChannel.write(buffer, attachment, new CompletionHandler<Integer, T>() {
			@Override
			public void completed(Integer result, T attachment) {
				if (completed != null) {
					completed.completed(result, attachment);
				} else {
					log.info("服务端向{}发送数据完毕", ServerSession.this.getRemoteAddress());
				}
			}

			@Override
			public void failed(Throwable exc, T attachment) {
				if (failed != null) {
					failed.failed(exc, attachment);
				} else {
					log.info("服务端向{}发送数据失败", ServerSession.this.getRemoteAddress());
				}
			}

		});
		return this;
	}

}
